frontend/pages/e/[uuid]/waitingList.tsx (view raw)
1import {useState, useEffect, useMemo} from 'react';
2import {makeStyles} from '@material-ui/core/styles';
3import {useTranslation} from 'react-i18next';
4import {initializeApollo} from '../../../lib/apolloClient';
5import useToastStore from '../../../stores/useToastStore';
6import useEventStore from '../../../stores/useEventStore';
7import Layout from '../../../layouts/Default';
8import {Travel as TravelType} from '../../../generated/graphql';
9import EventBar from '../../../containers/EventBar';
10import Loading from '../../../containers/Loading';
11import {
12 useUpdateEventMutation,
13 Event as EventType,
14 useEventByUuidQuery,
15 EventByUuidDocument,
16 EditEventInput,
17 useFindUserVehiclesQuery,
18} from '../../../generated/graphql';
19import ErrorPage from '../../_error';
20import useProfile from '../../../hooks/useProfile';
21import useBannerStore from '../../../stores/useBannerStore';
22import DrawerMenu from '../../../containers/DrawerMenu';
23import WaitingList from '../../../containers/WaitingList';
24import {
25 AddPassengerToTravel,
26 AddPassengerToWaitingList,
27} from '../../../containers/NewPassengerDialog';
28import AddToMyEventDialog from '../../../containers/AddToMyEventDialog';
29
30const POLL_INTERVAL = 10000;
31
32interface NewPassengerDialogContext {
33 addSelf: boolean;
34}
35
36interface Props {
37 event: EventType;
38 eventUUID: string;
39}
40
41const EventPage = props => {
42 const {t} = useTranslation();
43 const {event} = props;
44 if (!event) return <ErrorPage statusCode={404} title={t`event.not_found`} />;
45 return <Event {...props} />;
46};
47
48const Event = (props: Props) => {
49 const {eventUUID} = props;
50 const bannerOffset = useBannerStore(s => s.offset);
51 const classes = useStyles({bannerOffset});
52 const {t} = useTranslation();
53 const {user} = useProfile();
54 const {data: {me: {profile: {vehicles = []} = {}} = {}} = {}, loading} =
55 useFindUserVehiclesQuery();
56 const addToast = useToastStore(s => s.addToast);
57 const setEvent = useEventStore(s => s.setEvent);
58 const eventUpdate = useEventStore(s => s.event);
59 const setIsEditing = useEventStore(s => s.setIsEditing);
60 const [isAddToMyEvent, setIsAddToMyEvent] = useState(false);
61 const [addPassengerToWaitingListContext, toggleNewPassengerToWaitingList] =
62 useState<NewPassengerDialogContext | null>(null);
63 const [updateEvent] = useUpdateEventMutation();
64 const {data: {eventByUUID: event} = {}} = useEventByUuidQuery({
65 pollInterval: POLL_INTERVAL,
66 variables: {uuid: eventUUID},
67 });
68
69 useEffect(() => {
70 if (event) setEvent(event as EventType);
71 }, [event]);
72
73 const onSave = async e => {
74 try {
75 const {uuid, ...data} = eventUpdate;
76 const {id, __typename, travels, users, waitingList, ...input} = data;
77 await updateEvent({
78 variables: {uuid, eventUpdate: input as EditEventInput},
79 refetchQueries: ['eventByUUID'],
80 });
81 setIsEditing(false);
82 } catch (error) {
83 console.error(error);
84 addToast(t('event.errors.cant_update'));
85 }
86 };
87
88 const canAddSelf = useMemo(() => {
89 if (!user) return false;
90 const isInWaitingList = event?.waitingPassengers?.some(
91 passenger => passenger.user?.id === `${user.id}`
92 );
93 const isInTravel = event?.travels.some(travel =>
94 travel.passengers.some(passenger => passenger.user?.id === `${user.id}`)
95 );
96 return !(isInWaitingList || isInTravel);
97 }, [event, user]);
98
99 if (!event || loading) return <Loading />;
100
101 return (
102 <Layout
103 className={classes.layout}
104 pageTitle={t('event.title', {title: event.name})}
105 menuTitle={t('event.title', {title: event.name})}
106 displayMenu={false}
107 >
108 <EventBar event={event} onAdd={setIsAddToMyEvent} onSave={onSave} />
109 <DrawerMenu />
110 <WaitingList
111 canAddSelf={canAddSelf}
112 getToggleNewPassengerDialogFunction={(addSelf: boolean) => () =>
113 toggleNewPassengerToWaitingList({addSelf})}
114 />
115 <AddToMyEventDialog
116 event={event}
117 open={isAddToMyEvent}
118 onClose={() => setIsAddToMyEvent(false)}
119 />
120 {!!addPassengerToWaitingListContext && (
121 <AddPassengerToWaitingList
122 open={!!addPassengerToWaitingListContext}
123 toggle={() => toggleNewPassengerToWaitingList(null)}
124 addSelf={addPassengerToWaitingListContext.addSelf}
125 />
126 )}
127 </Layout>
128 );
129};
130
131export async function getServerSideProps(ctx) {
132 const {uuid} = ctx.query;
133 const apolloClient = initializeApollo();
134 const {data = {}} = await apolloClient.query({
135 query: EventByUuidDocument,
136 variables: {uuid},
137 });
138 const {eventByUUID: event} = data;
139 const {host = ''} = ctx.req.headers;
140
141 return {
142 props: {
143 event,
144 eventUUID: uuid,
145 metas: {
146 title: event?.name || '',
147 url: `https://${host}${ctx.resolvedUrl}`,
148 },
149 },
150 };
151}
152
153const useStyles = makeStyles(theme => ({
154 layout: ({bannerOffset}) => ({
155 paddingTop: theme.mixins.toolbar.minHeight + bannerOffset,
156 }),
157}));
158
159export default EventPage;